#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <pthread.h>
#include "Socket.hpp"
#include "log.hpp"

const std::string sep = "\r\n";
uint16_t defaultport = 8888;

class HttpServer;

class ThreadData
{
public:
    ThreadData(int fd, HttpServer *ts)
        : sockfd(fd), sur(ts)
    {
    }

public:
    int sockfd;
    HttpServer *sur;
};

class RequestHttp
{
public:
    void Deserialize(std::string httpreq)
    {
        std::string str;
        while (true)
        {
            std::size_t pos = httpreq.find(sep);
            str = httpreq.substr(0, pos);
            httpreq.erase(0, pos + sep.size());
            hreader.push_back(str);
            if (str.empty())
                break;
        }
        text = httpreq;
    }

    void Parse()
    {
        std::stringstream ss(hreader[0]);
        ss >> method >> url >> version;
        std::string path = "./root";
        if (url == "/" || url == "/index.html")
            file_path = path + "/index.html";
        else
        {
            file_path = path + url;
        }
    }

    void DebugPrint()
    {

        for (auto &it : hreader)
        {
            std::cout << "--------------------------------------" << std::endl;
            std::cout << it << std::endl;
        }
        std::cout << "--------------------------------------" << std::endl;
        std::cout << text << std::endl;
        std::cout << "--------------------------------------" << std::endl;
        std::cout << "method: " << method << std::endl;
        std::cout << "--------------------------------------" << std::endl;
        std::cout << "url: " << url << std::endl;
        std::cout << "--------------------------------------" << std::endl;
        std::cout << "version: " << version << std::endl;
        std::cout << "--------------------------------------" << std::endl;
        std::cout << "file_path: " << file_path << std::endl;
        std::cout << "--------------------------------------" << std::endl;
    }

public:
    std::vector<std::string> hreader;
    std::string text;

    std::string file_path ;
    std::string method;
    std::string url;
    std::string version;
};

class HttpServer
{

public:
    HttpServer(uint16_t port = defaultport)
        : port_(port)
    {
    }

    void Init()
    {
        listenfd.Socket();
        listenfd.Bind(port_);
        listenfd.Listen();
    }

    void Start()
    {
        std::string clientip;
        uint16_t port;
        while (true)
        {
            int sockfd = listenfd.Accept(&clientip, &port);
            lg(INFO, "get sockfd: %d", sockfd);
            lg(INFO, "accept success");
            if (sockfd < 0)
                continue;
            pthread_t tid;
            ThreadData *td = new ThreadData(sockfd, this);
            pthread_create(&tid, nullptr, ThreadRun, td);
        }
    }

    std::string ReadHtml(const std::string &path)
    {
        std::string text;
        std::string line;
        std::fstream on(path);
        if (!on.is_open())
            return "404";

        while (getline(on, line))
        {
            text += line;
        }

        on.close();
        return text;
    }

    void HttpResponseHandWrite(const ThreadData *td)
    {
        std::cout << "HttpResponseHandWrite Run" << std::endl;

        char buffer[10240];
        ssize_t n = recv(td->sockfd, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0;

            std::cout << buffer << std::endl;
            RequestHttp req;
            req.Deserialize(buffer);
            req.Parse();
            //req.DebugPrint();

            std::cout << buffer << std::endl;
            std::string response_line;
            std::string text = ReadHtml(req.file_path);
            response_line += "HTTP/1.0 200 OK\r\n";
            std::string response_header = "Content-Length: ";
            response_header += std::to_string(text.size());
            response_header += "\r\n";
            response_header += "Location: ";
            response_header += "https://www.qq.com";
            response_header += "\r\n";
            response_header += text;
            response_header += "\r\n";

            std::string response = response_line;
            response += response_header;
            response += sep;
            response += text;

            //std::cout << response_header << std::endl;
            send(td->sockfd, response.c_str(), response.size(), 0);
        }
        close(td->sockfd);
    }

    static void *ThreadRun(void *args)
    {

        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(args);
        std::cout << "线程创建成功" << std::endl;

        td->sur->HttpResponseHandWrite(td);

        delete td;
        return nullptr;
    }

    ~HttpServer()
    {
    }

private:
    Sock listenfd;
    uint16_t port_;
};
